package com.cxcs.cxcsojcodesandbox.utils;

import cn.hutool.core.util.StrUtil;
import com.cxcs.cxcsojcodesandbox.model.ExcuteMessage;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.StopWatch;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 获取进程执行结果 的工具类
 *
 * @Author: CxCS
 * @Version: 1.0
 * @Date: 2024-08
 */
public class ProcessUtils {
    /**
     *  获取进程执行后 返回的信息（结果）
     * @param process   进程
     * @param operName  操作名称
     * @return
     */
    public static ExcuteMessage getProcessMessge(Process process, String operName) {
        ExcuteMessage excuteMessage = new ExcuteMessage();

        try {

            int exitValue = process.waitFor(); // 执行错误码
            excuteMessage.setExitValue(exitValue);

            // 正常执行
            if (exitValue == 0) {
                System.out.println(operName + "操作执行成功！");
                // 获取进程的输出
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                List<String> outputStrList = new ArrayList<>(); // 存储输出的数据
                // 按行读取
                String compileOutputLine;
                while ((compileOutputLine = bufferedReader.readLine()) != null) {
                    outputStrList.add(compileOutputLine);
                }

                excuteMessage.setMessage(StringUtils.join(outputStrList, "\n"));  // 拼接换行符
//                System.out.println(compileOutputStringBuilder);
            } else {
                System.out.println(operName + "操作执行失败，错误码：" + exitValue);
                // 获取进程的正常输出内容
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
                List<String> outputStrList = new ArrayList<>(); // 存储输出的数据
                // 按行读取
                String compileOutputLine;
                while ((compileOutputLine = bufferedReader.readLine()) != null) {
                    outputStrList.add(compileOutputLine);
                }

                // 获取进程输出的 错误信息
                BufferedReader errorBufferedReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
                List<String> errorOutputStrList = new ArrayList<>(); // 存储输出的数据
                // 按行读取
                String errorCompileOutputLine;
                while ((errorCompileOutputLine = errorBufferedReader.readLine()) != null) {
                    errorOutputStrList.add(errorCompileOutputLine);
                }
//                System.out.println(errorOutputStrList);

                excuteMessage.setMessage(StringUtils.join(outputStrList, "\n"));  // 拼接换行符
                excuteMessage.setErrorMessage(StringUtils.join(errorOutputStrList, "\n"));
            }

        } catch (IOException | InterruptedException e) {
            throw new RuntimeException(e);
        }

        return excuteMessage;
    }

    /**
     *  运行程序后，进行交互式输入（Scanner等）
     *
     * @param process
     * @param inputArgs 一组输入用例
     * @param operName
     * @return
     */
    public static ExcuteMessage runInteractProcess(Process process, String inputArgs, String operName) {
        ExcuteMessage excuteMessage = new ExcuteMessage();

        try {
            StopWatch stopWatch = new StopWatch(); // 引入Spring的计时类
            stopWatch.start();

            // 向控制台输入数据
            OutputStreamWriter outputStreamWriter = new OutputStreamWriter(process.getOutputStream()); // 获取 进程输出流

            // 输入用例 变为换行输入
            String inputList[] = inputArgs.split(" ");
            String inputStr = StrUtil.join("\n", inputList) + "\n";
            outputStreamWriter.write(inputStr);
            outputStreamWriter.flush();  // 刷新(回车)

            excuteMessage = ProcessUtils.getProcessMessge(process, operName);  // 获取执行结果

            outputStreamWriter.close();
            process.destroy();

            // 执行结束，获取执行时间
            stopWatch.stop();
            excuteMessage.setRunTime(stopWatch.getLastTaskTimeMillis());

        } catch (IOException e) {
            e.printStackTrace();
        }

        return excuteMessage;
    }
}
